﻿#region License
/*
Copyright (c) <2012> <Nercoding>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Original Code by Gastric of Dawnsong
 */
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.IO;
using System.Windows.Forms;
using System.Xml.Linq;

namespace AC2_MultiClient.Managers
{
    public class XmlManager
    {
        /// <summary>
        /// A List of servers from our Ac2Servers.xml file
        /// </summary>
        public static List<string> ServerList = new List<string>();
        /// <summary>
        /// A List of users from our Config.xml
        /// </summary>
        public static List<string> UserList = new List<string>();
        /// <summary>
        ///  A List of Directories from our Config.xml
        /// </summary>
        public static List<string> Directories = new List<string>();
        /// <summary>
        /// Attempts to load our xml files, if it cant, it creates them
        /// </summary>
        public static void Load()
        {
            try
            {
                XmlDocument Doc = new XmlDocument();
                Doc.Load(Globals.ServerConfigXML);
            }
            catch
            {
                CreateServerConfigFile();
            }

            try
            {
                XmlDocument Doc = new XmlDocument();
                Doc.Load(Globals.ConfigXml);
            }
            catch
            {
                CreateConfig();
            }

            // try to load them all
            try
            {
                XmlDocument Doc = new XmlDocument();
                LoadServerConfig(Doc);
            }
            catch { MessageBox.Show("Error Loading Servers"); }

            try
            {
                XmlDocument Doc = new XmlDocument();
                LoadUserConfig(Doc);
            }
            catch { MessageBox.Show("Error Loading Users"); }

            try
            {
                XmlDocument Doc = new XmlDocument();
                LoadDirectoryConfig(Doc);
            }
            catch { MessageBox.Show("Error Loading Directories"); }
        }
        /// <summary>
        /// Loads our server config file and populates our data
        /// </summary>
        public static void LoadServerConfig(XmlDocument doc)
        {
            if (File.Exists(Globals.ServerConfigXML))
            {
                doc.Load(Globals.ServerConfigXML);

                XmlNodeList list = doc.SelectNodes("/ROOT/Servers/Server");
                if (list.Count > 0)
                {
                    foreach (XmlNode n in list)
                    {
                        if (!ServerList.Contains(n["Servername"].InnerText))
                        {
                            ServerList.Add(n["Servername"].InnerText);
                        }
                    }
                }
            }
            else
                MessageBox.Show("Unable to Load Server Config");
        }
        /// <summary>
        /// Loads our Config.xml Users section, and populates our data
        /// </summary>
        /// <param name="doc">A new XmlDocument (XmlDocument Doc = new XmlDocument();)</param>
        public static void LoadUserConfig(XmlDocument doc)
        {
            if (File.Exists(Globals.ConfigXml))
            {
                doc.Load(Globals.ConfigXml);

                XmlNodeList ulist = doc.SelectNodes("/ROOT/Users/User");
                if (ulist.Count > 0)
                {
                    foreach (XmlNode u in ulist)
                    {
                        if (u["Username"].InnerText != "None")
                        {
                            UserList.Add(u["Username"].InnerText);
                        }
                    }
                }
            }
            else
                MessageBox.Show("Unable to Load Config");
        }
        /// <summary>
        /// Loads our Config.xml Directory section, and populates our data
        /// </summary>
        /// <param name="doc">A new XmlDocument (XmlDocument Doc = new XmlDocument();)</param>
        public static void LoadDirectoryConfig(XmlDocument doc)
        {
            if (File.Exists(Globals.ConfigXml))
            {
                doc.Load(Globals.ConfigXml);

                XmlNodeList ulist = doc.SelectNodes("/ROOT/Directories/Directory");
                if (ulist.Count > 0)
                {
                    foreach (XmlNode u in ulist)
                    {
                        if (u["DirectoryLocation"].InnerText != "None")
                        {
                            Directories.Add(u["DirectoryLocation"].InnerText);
                        }
                    }
                }
            }
            else
                MessageBox.Show("Unable to Load Config");
        }
        /// <summary>
        /// Creates our default server config file
        /// </summary>
        public static void CreateServerConfigFile()
        {
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("AC2 Multi Client Server Config"),
                new XElement("ROOT",
                    new XElement("Servers",
                        new XElement("Server",
                    new XElement("Servername", "Dawnsong")))));
            // Save it
            doc.Save(Globals.ServerConfigXML);
        }
        /// <summary>
        /// Creates our default Config.xml
        /// </summary>
        public static void CreateConfig()
        {

            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XComment("AC2 Multi Client User and Directory Config"),
                new XElement("ROOT",
                    new XElement("Users",
                        new XElement("User",
                    new XElement("Username", "None"))),
                    new XComment("Directories"),
                    new XElement("Directories",
                    new XElement("Directory",
                    new XElement("DirectoryLocation", "None")))));

            doc.Save(Globals.ConfigXml);
        }
        /// <summary>
        /// Adds a user name to our Config.xml
        /// </summary>
        /// <param name="user">The user to add</param>
        /// <returns>True if able toadd user</returns>
        public static bool AddUser(string user)
        {
            // On the first add of a new user, remove our default
            if (IsUserInConfig("None")) { RemoveUser("None"); }

            try
            {
                XDocument doc = XDocument.Load(Globals.ConfigXml);
                var a = doc.Root.Element("Users");
                a.Add(new XElement("User",
                    new XElement("Username", user)));
                
                doc.Save(Globals.ConfigXml);
                if (!UserList.Contains(user)) { UserList.Add(user); }
                return true;
            }
            catch { return false; }
        }
        /// <summary>
        /// Removes a username from our Config.xml
        /// </summary>
        /// <param name="user">The User name to remove</param>
        /// <returns>True is able to remove user</returns>
        public static bool RemoveUser(string user)
        {
            try
            {
                XDocument doc = XDocument.Load(Globals.ConfigXml);
                XElement toRemove = doc.Descendants("Users")
                 .Descendants("User")
                 .Where(x => x.Element("Username").Value == user)
                 .First<XElement>();
                if (UserList.Contains(user)) { UserList.Remove(user); }
                toRemove.Remove();
                doc.Save(Globals.ConfigXml);
                return true;
            }
            catch { return false; }
        }
        /// <summary>
        /// Adds a Directory to our Config.xml
        /// </summary>
        /// <param name="loc">The Directory to add, ending in \\ac2launcher.exe</param>
        /// <returns>True if able to add</returns>
        public static bool AddDirectoryLocation(string loc)
        {
            // If our default Directory of none is in our file, remove it
            if (IsDirectoryLocInConfig("None")) { RemoveDirectoryLocation("None"); }
            try
            {
                XDocument doc = XDocument.Load(Globals.ConfigXml);
                var a = doc.Root.Element("Directories");
                a.Add(new XElement("Directory",
                    new XElement("DirectoryLocation", loc)));
                if (!Directories.Contains(loc)) { Directories.Add(loc); }
                doc.Save(Globals.ConfigXml);
                return true;
            }
            catch { return false; }
        }
        /// <summary>
        /// Removes a Directory from our config.xml
        /// </summary>
        /// <param name="loc">The Directory to remove with \\ac2launcher.exe</param>
        /// <returns>True if able to remove this directory</returns>
        public static bool RemoveDirectoryLocation(string loc)
        {
            try
            {
                XDocument doc = XDocument.Load(Globals.ConfigXml);
                XElement toRemove = doc.Descendants("Directories")
                 .Descendants("Directory")
                 .Where(x => x.Element("DirectoryLocation").Value == loc)
                 .First<XElement>();
                if (Directories.Contains(loc)) { Directories.Remove(loc); }
                toRemove.Remove();
                doc.Save(Globals.ConfigXml);
                return true;
            }
            catch { return false; }
        }
        /// <summary>
        /// Checks to see if a Username exists in our Config.xml
        /// </summary>
        /// <param name="user">The username to check</param>
        /// <returns>True if the user exists</returns>
        public static bool IsUserInConfig(string user)
        {
            try
            {
                XDocument doc = XDocument.Load(Globals.ConfigXml);
                XElement toRemove = doc.Descendants("Users")
                 .Descendants("User")
                 .Where(x => x.Element("Username").Value == user)
                 .First<XElement>();
                return true;
            }
            catch { return false; }

        }
        /// <summary>
        /// Checks if a Directory Location is present in our Config.xml
        /// </summary>
        /// <param name="loc">The Directory to check</param>
        /// <returns>True if loc exists in our config.xml</returns>
        public static bool IsDirectoryLocInConfig(string loc)
        {
            try
            {
                XDocument doc = XDocument.Load(Globals.ConfigXml);
                XElement toRemove = doc.Descendants("Directories")
                 .Descendants("Directory")
                 .Where(x => x.Element("DirectoryLocation").Value == loc)
                 .First<XElement>();
                return true;
            }
            catch { return false; }
        }
    }
}
